#include "img_sender.h"
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <err.h>

#if (0) 
#define STRACE(a) { printf("%s\n", a); }
#define SSTRACE(a,b) { printf("%s %s\n", a, b); }
#define SITRACE(a,b) { printf("%s %d\n", a, b); }
#else
#define STRACE(a)
#define SSTRACE(a,b)
#define SITRACE(a,b)
#endif

int img_send(const char* blob, int bloblen) {
  return img_send_hp(blob, bloblen, IMG_HOST, IMG_PORT);
}

#define SEND_BLOCK_SIZE 1024
int send_whole(int sock, const char *blob, int bloblen) {
  int sent = 0;
  SITRACE("start sending", bloblen)
  while (sent < bloblen) {
    int count = SEND_BLOCK_SIZE;
    int new_sent = 0;
    if (bloblen - sent < count) 
      count = bloblen - sent;
    STRACE("doing a write");
    new_sent = write(sock, blob+sent, count);
    STRACE("done a write");
    SITRACE("new_sent ", new_sent)
    if (new_sent == -1) {
      SITRACE("sending failed, but already sent", sent)
      return -1;
    }
    sent += new_sent;
    SITRACE("sent ", sent)
  }
  SITRACE ("brilliant, all sent ", sent)
  return 0;
}

#define RECEIVE_BLOCK_SIZE 1024
int receive_whole(int sock) {
  char buf[RECEIVE_BLOCK_SIZE];
  int received;
  received = recv(sock, buf, RECEIVE_BLOCK_SIZE, 0);
  SITRACE("receive_whole received on first try", received);
  if (received < 15) {
    SITRACE("receive_while received not enough", received);
    return -1;
  }
  if (strncmp("HTTP/1.0 200 OK", buf, 15) == 0) {
    STRACE("receive_whole: It worked ;-)");
    STRACE("try to empty buffer");
    received = recv(sock, buf, RECEIVE_BLOCK_SIZE, 0);
    if (received > 0) {
      received = recv(sock, buf, RECEIVE_BLOCK_SIZE, 0);
    }
    if (received > 0) {
      received = recv(sock, buf, RECEIVE_BLOCK_SIZE, 0);
    }
    if (received > 0) {
      received = recv(sock, buf, RECEIVE_BLOCK_SIZE, 0);
    }
    return 0;
  } else {
    STRACE("receive_whole: nope :-(");
    buf[received] = 0;
    STRACE(buf);
    return -1;
  }
}

/* send a blob using socket api simulating HTTP */
int img_send_hp(const char* blob, int bloblen, 
		const char* hostname, int port) {
  char query[100];
  int sock = -1;
  struct addrinfo hints;
  struct addrinfo *result;
  struct addrinfo *rp;
  int ret;

  /* socket stuff first */
  char service[20];
  sprintf(service, "%d", port);
  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_NUMERICSERV;
  hints.ai_protocol = 0;
  ret = getaddrinfo(hostname, service,
		    &hints,
		    &result);
  if (ret != 0) {
    STRACE("getaddrinfo failed");
    return -1;
  } else {
    STRACE("getaddrinfo fine :-)");
  }
  for (rp=result; rp != NULL; rp = rp->ai_next) {
    sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
    if (sock == -1) {
      STRACE("getaddrinfo, no the right one");
      continue;
    } else {
      STRACE("getaddrinfo, the right one :-)");
    }
    if (connect(sock, rp->ai_addr, rp->ai_addrlen) == 0) {
      STRACE("getaddrinfo, got one");
      break; /* got one */
    } else {
      SITRACE("error", errno);
      STRACE("getaddrinfo, the right one didn't bind :-(");
    }
    close(sock);
  }
  if (rp == NULL) {
    STRACE("didn't get a connection :-(");
    return -1; /* didn't get a connection */
  } else {
    STRACE("got a connection :-)");
  }
  freeaddrinfo(result); /* connection info no longer needed */
  sprintf(query, "POST put?size=%d HTTP/1.0\n", bloblen);
  if (send_whole(sock, query, strlen(query)) != 0) {
    STRACE("failed sending request header");
    return -1;
  } else {
    STRACE("sent request header");
  }
  sprintf(query, "Content-Length: %d\n", bloblen);
  if (send_whole(sock, query, strlen(query)) != 0) {
    STRACE("failed sending Content-Length");
    return -1;
  }  else {
    STRACE("sent Content-Length :-)");
  }
  sprintf(query, "Content-Type: application/binary\n");
  if (send_whole(sock, query, strlen(query)) != 0) {
    STRACE("failed sending Content-Type");
    return -1;
  } else {
    STRACE("sent Content-Type :-)");
  }
  sprintf(query, "\n");
  if (send_whole(sock, query, strlen(query)) != 0) {
    STRACE("failed sending empty line");
  } else {
    STRACE("sent empty line :-)");
  }
  if (send_whole(sock, blob, bloblen) != 0)  {
    SITRACE("failed sending blob ", bloblen)
    return -1;
  } else {
    SITRACE("sent blob :-) ", bloblen)
  }
  if (receive_whole(sock) != 0) {
    STRACE("error reading response")
    return -1;
  } else {
    STRACE("fine reading response")
  }
  close(sock);
  return 0;
}



